﻿using System;
using OpenMetaverse;

namespace CableBeachMessages
{
    /// <summary>
    /// The different types of grid assets
    /// </summary>
    public enum AssetType : sbyte
    {
        /// <summary>Unknown asset type</summary>
        Unknown = -1,
        /// <summary>Texture asset, stores in JPEG2000 J2C stream format</summary>
        Texture = 0,
        /// <summary>Sound asset</summary>
        Sound = 1,
        /// <summary>Calling card for another avatar</summary>
        CallingCard = 2,
        /// <summary>Link to a location in world</summary>
        Landmark = 3,
        // <summary>Legacy script asset, you should never see one of these</summary>
        //[Obsolete]
        //Script = 4,
        /// <summary>Collection of textures and parameters that can be 
        /// worn by an avatar</summary>
        Clothing = 5,
        /// <summary>Primitive that can contain textures, sounds, 
        /// scripts and more</summary>
        Object = 6,
        /// <summary>Notecard asset</summary>
        Notecard = 7,
        /// <summary>Holds a collection of inventory items</summary>
        Folder = 8,
        /// <summary>Root inventory folder</summary>
        RootFolder = 9,
        /// <summary>Linden scripting language script</summary>
        LSLText = 10,
        /// <summary>LSO bytecode for a script</summary>
        LSLBytecode = 11,
        /// <summary>Uncompressed TGA texture</summary>
        TextureTGA = 12,
        /// <summary>Collection of textures and shape parameters that can
        /// be worn</summary>
        Bodypart = 13,
        /// <summary>Trash folder</summary>
        TrashFolder = 14,
        /// <summary>Snapshot folder</summary>
        SnapshotFolder = 15,
        /// <summary>Lost and found folder</summary>
        LostAndFoundFolder = 16,
        /// <summary>Uncompressed sound</summary>
        SoundWAV = 17,
        /// <summary>Uncompressed TGA non-square image, not to be used as a
        /// texture</summary>
        ImageTGA = 18,
        /// <summary>Compressed JPEG non-square image, not to be used as a
        /// texture</summary>
        ImageJPEG = 19,
        /// <summary>Animation</summary>
        Animation = 20,
        /// <summary>Sequence of animations, sounds, chat, and pauses</summary>
        Gesture = 21,
        /// <summary>Simstate file</summary>
        Simstate = 22,
        /// <summary>OGRE mesh</summary>
        OgreMesh = 43,
        /// <summary>OGRE skeleton</summary>
        OgreSkeleton = 44,
        /// <summary>OGRE material</summary>
        OgreMaterial = 45,
        /// <summary>XML</summary>
        Xml = 46,
        /// <summary>OGRE particle script</summary>
        OgreParticle = 47,
        /// <summary>Flash animation</summary>
        FlashAnimation = 49,
    }

    /// <summary>
    /// Inventory Item Types, eg Script, Notecard, Folder, etc
    /// </summary>
    public enum InventoryType : sbyte
    {
        /// <summary>Unknown</summary>
        Unknown = -1,
        /// <summary>Texture</summary>
        Texture = 0,
        /// <summary>Sound</summary>
        Sound = 1,
        /// <summary>Calling Card</summary>
        CallingCard = 2,
        /// <summary>Landmark</summary>
        Landmark = 3,
        /*
        /// <summary>Script</summary>
        //[Obsolete("See LSL")] Script = 4,
        /// <summary>Clothing</summary>
        //[Obsolete("See Wearable")] Clothing = 5,
        /// <summary>Object, both single and coalesced</summary>
         */
        Object = 6,
        /// <summary>Notecard</summary>
        Notecard = 7,
        /// <summary></summary>
        Category = 8,
        /// <summary>Folder</summary>
        Folder = 8,
        /// <summary></summary>
        RootCategory = 9,
        /// <summary>an LSL Script</summary>
        LSL = 10,
        /*
        /// <summary></summary>
        //[Obsolete("See LSL")] LSLBytecode = 11,
        /// <summary></summary>
        //[Obsolete("See Texture")] TextureTGA = 12,
        /// <summary></summary>
        //[Obsolete] Bodypart = 13,
        /// <summary></summary>
        //[Obsolete] Trash = 14,
         */
        /// <summary></summary>
        Snapshot = 15,
        /*
        /// <summary></summary>
        //[Obsolete] LostAndFound = 16,
         */
        /// <summary></summary>
        Attachment = 17,
        /// <summary></summary>
        Wearable = 18,
        /// <summary></summary>
        Animation = 19,
        /// <summary></summary>
        Gesture = 20,
        /// <summary>OGRE mesh</summary>
        OgreMesh = 6,
        /// <summary>OGRE skeleton</summary>
        OgreSkeleton = 19,
        /// <summary>OGRE material</summary>
        OgreMaterial = 41,
        /// <summary>OGRE particle script</summary>
        OgrePartice = 41,
        /// <summary>Flash animation</summary>
        FlashAnimation = 42,
    }

    public static class CableBeachUtils
    {
        // The following section is based on the table at https://wiki.secondlife.com/wiki/Asset_System

        #region SL / file extension / content-type conversions

        public static string SLAssetTypeToContentType(int assetType)
        {
            switch ((AssetType)assetType)
            {
                case AssetType.Texture:
                    return "image/x-j2c";
                case AssetType.Sound:
                    return "application/ogg";
                case AssetType.CallingCard:
                    return "application/vnd.ll.callingcard";
                case AssetType.Landmark:
                    return "application/vnd.ll.landmark";
                case AssetType.Clothing:
                    return "application/vnd.ll.clothing";
                case AssetType.Object:
                    return "application/vnd.ll.primitive";
                case AssetType.Notecard:
                    return "application/vnd.ll.notecard";
                case AssetType.Folder:
                    return "application/vnd.ll.folder";
                case AssetType.RootFolder:
                    return "application/vnd.ll.rootfolder";
                case AssetType.LSLText:
                    return "application/vnd.ll.lsltext";
                case AssetType.LSLBytecode:
                    return "application/vnd.ll.lslbyte";
                case AssetType.TextureTGA:
                case AssetType.ImageTGA:
                    return "image/tga";
                case AssetType.Bodypart:
                    return "application/vnd.ll.bodypart";
                case AssetType.TrashFolder:
                    return "application/vnd.ll.trashfolder";
                case AssetType.SnapshotFolder:
                    return "application/vnd.ll.snapshotfolder";
                case AssetType.LostAndFoundFolder:
                    return "application/vnd.ll.lostandfoundfolder";
                case AssetType.SoundWAV:
                    return "audio/x-wav";
                case AssetType.ImageJPEG:
                    return "image/jpeg";
                case AssetType.Animation:
                    return "application/vnd.ll.animation";
                case AssetType.Gesture:
                    return "application/vnd.ll.gesture";
                case AssetType.OgreMaterial:
                    return "application/vnd.rex.ogremate";
                case AssetType.OgreMesh:
                    return "application/vnd.rex.ogremesh";
                case AssetType.OgreParticle:
                    return "application/vnd.rex.ogrepart";
                case AssetType.OgreSkeleton:
                    return "application/vnd.rex.ogreskel";
                case AssetType.FlashAnimation:
                    return "application/x-shockwave-flash";
                case AssetType.Simstate:
                    return "application/x-metaverse-simstate";
                case AssetType.Xml:
                    return "application/xml";
                case AssetType.Unknown:
                default:
                    return "application/octet-stream";
            }
        }

        public static sbyte ContentTypeToSLAssetType(string contentType)
        {
            switch (contentType)
            {
                case "image/x-j2c":
                case "image/jp2":
                    return (sbyte)AssetType.Texture;
                case "application/ogg":
                    return (sbyte)AssetType.Sound;
                case "application/vnd.ll.callingcard":
                case "application/x-metaverse-callingcard":
                    return (sbyte)AssetType.CallingCard;
                case "application/vnd.ll.landmark":
                case "application/x-metaverse-landmark":
                    return (sbyte)AssetType.Landmark;
                case "application/vnd.ll.clothing":
                case "application/x-metaverse-clothing":
                    return (sbyte)AssetType.Clothing;
                case "application/vnd.ll.primitive":
                case "application/x-metaverse-primitive":
                    return (sbyte)AssetType.Object;
                case "application/vnd.ll.notecard":
                case "application/x-metaverse-notecard":
                    return (sbyte)AssetType.Notecard;
                case "application/vnd.ll.folder":
                    return (sbyte)AssetType.Folder;
                case "application/vnd.ll.rootfolder":
                    return (sbyte)AssetType.RootFolder;
                case "application/vnd.ll.lsltext":
                case "application/x-metaverse-lsl":
                    return (sbyte)AssetType.LSLText;
                case "application/vnd.ll.lslbyte":
                case "application/x-metaverse-lso":
                    return (sbyte)AssetType.LSLBytecode;
                case "image/tga":
                    // Note that AssetType.TextureTGA will be converted to AssetType.ImageTGA
                    return (sbyte)AssetType.ImageTGA;
                case "application/vnd.ll.bodypart":
                case "application/x-metaverse-bodypart":
                    return (sbyte)AssetType.Bodypart;
                case "application/vnd.ll.trashfolder":
                    return (sbyte)AssetType.TrashFolder;
                case "application/vnd.ll.snapshotfolder":
                    return (sbyte)AssetType.SnapshotFolder;
                case "application/vnd.ll.lostandfoundfolder":
                    return (sbyte)AssetType.LostAndFoundFolder;
                case "audio/x-wav":
                    return (sbyte)AssetType.SoundWAV;
                case "image/jpeg":
                    return (sbyte)AssetType.ImageJPEG;
                case "application/vnd.ll.animation":
                case "application/x-metaverse-animation":
                    return (sbyte)AssetType.Animation;
                case "application/vnd.ll.gesture":
                case "application/x-metaverse-gesture":
                    return (sbyte)AssetType.Gesture;
                case "application/x-metaverse-simstate":
                    return (sbyte)AssetType.Simstate;
                case "application/vnd.rex.ogremate":
                    return (sbyte)AssetType.OgreMaterial;
                case "application/vnd.rex.ogremesh":
                    return (sbyte)AssetType.OgreMesh;
                case "application/vnd.rex.ogrepart":
                    return (sbyte)AssetType.OgreParticle;
                case "application/vnd.rex.ogreskel":
                    return (sbyte)AssetType.OgreSkeleton;
                case "application/x-shockwave-flash":
                    return (sbyte)AssetType.FlashAnimation;
                case "application/xml":
                case "text/xml":
                    return (sbyte)AssetType.Xml;
                case "application/octet-stream":
                default:
                    return (sbyte)AssetType.Unknown;
            }
        }

        public static sbyte ContentTypeToSLInvType(string contentType)
        {
            switch (contentType)
            {
                case "image/x-j2c":
                case "image/jp2":
                case "image/tga":
                case "image/jpeg":
                    return (sbyte)InventoryType.Texture;
                case "application/ogg":
                case "audio/x-wav":
                    return (sbyte)InventoryType.Sound;
                case "application/vnd.ll.callingcard":
                case "application/x-metaverse-callingcard":
                    return (sbyte)InventoryType.CallingCard;
                case "application/vnd.ll.landmark":
                case "application/x-metaverse-landmark":
                    return (sbyte)InventoryType.Landmark;
                case "application/vnd.ll.clothing":
                case "application/x-metaverse-clothing":
                case "application/vnd.ll.bodypart":
                case "application/x-metaverse-bodypart":
                    return (sbyte)InventoryType.Wearable;
                case "application/vnd.ll.primitive":
                case "application/x-metaverse-primitive":
                    return (sbyte)InventoryType.Object;
                case "application/vnd.ll.notecard":
                case "application/x-metaverse-notecard":
                    return (sbyte)InventoryType.Notecard;
                case "application/vnd.ll.folder":
                    return (sbyte)InventoryType.Folder;
                case "application/vnd.ll.rootfolder":
                    return (sbyte)InventoryType.RootCategory;
                case "application/vnd.ll.lsltext":
                case "application/x-metaverse-lsl":
                case "application/vnd.ll.lslbyte":
                case "application/x-metaverse-lso":
                    return (sbyte)InventoryType.LSL;
                case "application/vnd.ll.trashfolder":
                case "application/vnd.ll.snapshotfolder":
                case "application/vnd.ll.lostandfoundfolder":
                    return (sbyte)InventoryType.Folder;
                case "application/vnd.ll.animation":
                case "application/x-metaverse-animation":
                    return (sbyte)InventoryType.Animation;
                case "application/vnd.ll.gesture":
                case "application/x-metaverse-gesture":
                    return (sbyte)InventoryType.Gesture;
                case "application/x-metaverse-simstate":
                    return (sbyte)InventoryType.Snapshot;
                case "application/vnd.rex.ogremate":
                    return (sbyte)InventoryType.OgreMaterial;
                case "application/vnd.rex.ogremesh":
                    return (sbyte)InventoryType.OgreMesh;
                case "application/vnd.rex.ogrepart":
                    return (sbyte)InventoryType.OgrePartice;
                case "application/vnd.rex.ogreskel":
                    return (sbyte)InventoryType.OgreSkeleton;
                case "application/x-shockwave-flash":
                    return (sbyte)InventoryType.FlashAnimation;
                case "application/octet-stream":
                default:
                    return (sbyte)InventoryType.Unknown;
            }
        }

        public static string ContentTypeToExtension(string contentType)
        {
            switch (contentType)
            {
                case "image/x-j2c":
                case "image/jp2":
                    return "texture";
                case "application/ogg":
                    return "ogg";
                case "application/vnd.ll.callingcard":
                case "application/x-metaverse-callingcard":
                    return "callingcard";
                case "application/vnd.ll.landmark":
                case "application/x-metaverse-landmark":
                    return "landmark";
                case "application/vnd.ll.clothing":
                case "application/x-metaverse-clothing":
                    return "clothing";
                case "application/vnd.ll.primitive":
                case "application/x-metaverse-primitive":
                    return "primitive";
                case "application/vnd.ll.notecard":
                case "application/x-metaverse-notecard":
                    return "notecard";
                case "application/vnd.ll.folder":
                    return "folder";
                case "application/vnd.ll.rootfolder":
                    return "rootfolder";
                case "application/vnd.ll.lsltext":
                case "application/x-metaverse-lsl":
                    return "lsltext";
                case "application/vnd.ll.lslbyte":
                case "application/x-metaverse-lso":
                    return "lslbyte";
                case "image/tga":
                    return "tga";
                case "application/vnd.ll.bodypart":
                case "application/x-metaverse-bodypart":
                    return "bodypart";
                case "application/vnd.ll.trashfolder":
                    return "trashfolder";
                case "application/vnd.ll.snapshotfolder":
                    return "snapshotfolder";
                case "application/vnd.ll.lostandfoundfolder":
                    return "lostandfoundfolder";
                case "audio/x-wav":
                    return "wav";
                case "image/jpeg":
                    return "jpg";
                case "application/vnd.ll.animation":
                case "application/x-metaverse-animation":
                    return "animatn";
                case "application/vnd.ll.gesture":
                case "application/x-metaverse-gesture":
                    return "gesture";
                case "application/x-metaverse-simstate":
                    return "simstate";
                case "application/octet-stream":
                default:
                    return "binary";
            }
        }

        public static string ExtensionToContentType(string extension)
        {
            switch (extension)
            {
                case "texture":
                    return "image/x-j2c";
                case "ogg":
                    return "application/ogg";
                case "callingcard":
                    return "application/vnd.ll.callingcard";
                case "landmark":
                    return "application/vnd.ll.landmark";
                case "clothing":
                    return "application/vnd.ll.clothing";
                case "primitive":
                    return "application/vnd.ll.primitive";
                case "notecard":
                    return "application/vnd.ll.notecard";
                case "folder":
                    return "application/vnd.ll.folder";
                case "rootfolder":
                    return "application/vnd.ll.rootfolder";
                case "lsltext":
                    return "application/vnd.ll.lsltext";
                case "lslbyte":
                    return "application/vnd.ll.lslbyte";
                case "tga":
                    return "image/tga";
                case "bodypart":
                    return "application/vnd.ll.bodypart";
                case "trashfolder":
                    return "application/vnd.ll.trashfolder";
                case "snapshotfolder":
                    return "application/vnd.ll.snapshotfolder";
                case "lostandfoundfolder":
                    return "application/vnd.ll.lostandfoundfolder";
                case "wav":
                    return "audio/x-wav";
                case "jpg":
                    return "image/jpeg";
                case "animatn":
                    return "application/vnd.ll.animation";
                case "gesture":
                    return "application/vnd.ll.gesture";
                case "binary":
                default:
                    return "application/octet-stream";
            }
        }

        #endregion SL / file extension / content-type conversions

        public static UUID MessageToUUID(Uri identity, UUID agentID)
        {
            if (agentID != UUID.Zero)
                return agentID;
            else if (identity != null)
                return IdentityToUUID(identity);
            else
                return UUID.Zero;
        }

        public static UUID IdentityToUUID(Uri identity)
        {
            return new UUID((OpenMetaverse.Utils.MD5(System.Text.Encoding.UTF8.GetBytes(identity.ToString()))), 0);
        }
    }
}
